package o2o.service.code.impl;

import com.jinyou.utils.common.DateUtils;
import com.jinyou.utils.common.JYFileUtils;
import com.jinyou.utils.common.ValidateUtil;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import o2o.config.dao.UserDaoSql;
import o2o.config.dao.utils.DaoUtils;
import o2o.config.dao.utils.Expression;
import o2o.config.dao.utils.QueryCondition;
import o2o.dao.PO.PojoTables;
import o2o.dao.PO.code.DiscountExchangeCodeInfo;
import o2o.dao.PO.code.TableCodeSequenceInfo;
import o2o.service.code.DiscountExchangeCodeService;
import o2o.service.code.TableCodeSequenceService;
import o2o.system.data.SYS_CONFIG_PATH;
import o2o.utils.CommonUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringValueResolver;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @User: @Created by yangtk
 * @Date: @Date 2020/12/1 14:11
 * @Email: yangtongkuan@qq.com
 * @To change this template use File | Settings | File Templates.
 * @desc 折扣兑换码
 */
@Service
public class DiscountExchangeCodeServiceImpl implements DiscountExchangeCodeService {

    private static int step = 0;
    private static int maxDigit = 0;

    @Autowired
    private TableCodeSequenceService tableCodeSequenceService;

    @Override
    public void batchGenerateExchangeCode(DiscountExchangeCodeInfo info, Integer generateSize) throws Exception {
        String format = new SimpleDateFormat("yy-MM").format(new Date());
        TableCodeSequenceInfo exchangeCode = tableCodeSequenceService.getOrCreateTableCodeSequenceByTypeAndKey(format, "discount_exchange_code");
        if (exchangeCode == null) {
            throw new Exception("生成兑换码失败,请稍后重试");
        }
        List<String> containerList = new ArrayList<>();
        Integer sequence = this.batchGenerateExchangeCode(format, exchangeCode.getSequence(), generateSize, containerList);
        if (containerList.size() - generateSize != 0) {
            throw new Exception("部分生成失败,请稍后重试");
        }
        info.setCreateTime(DateUtils.getCurrTime());
        Connection conn = null;
        try {
            conn = UserDaoSql.getInstance().getConnection();
            conn.setAutoCommit(false);
            // i. // 批量插入
            batchInsertExchangeCode(info, containerList, conn);
            // ii. // 2. 提交
            boolean flag = tableCodeSequenceService.updateTableSequenceByKey(exchangeCode.getType(), exchangeCode.getCode(), exchangeCode.getfVersion(), sequence);
            if (!flag) {
                throw new Exception("生成失败,请稍后重试");
            }
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
            UserDaoSql.getInstance().rollback(conn);
            UserDaoSql.getInstance().close(conn);
        } finally {
            UserDaoSql.getInstance().close(conn);
        }
    }

    @Override
    public void delDiscountExchangeCodeByCode(String code, String opUser) throws Exception {
        DiscountExchangeCodeInfo codeInfo = this.findDiscountExchangeCodeByCode(code);
        if (codeInfo == null) {
            throw new Exception("未获取兑换码信息");
        }

        if (codeInfo.getIsUse() == 1) {
            throw new Exception("已使用,不可删除");
        }
        StringBuilder sql = new StringBuilder();
        sql.append(" update ").append(PojoTables.DISCOUNT_EXCHANGE_CODE)
                .append(" set delFlag = 1")
                .append(", updateUser ='").append(opUser).append("' ")
                .append(" where delFlag = 0  and exchangeCode ='").append(code).append("' ");
        UserDaoSql.getInstance().executeBySql(sql.toString());
    }

    @Override
    public DiscountExchangeCodeInfo findDiscountExchangeCodeByCode(String code) {
        QueryCondition query = QueryCondition.getInstance();
        Expression expression = Expression.getInstance();
        expression.addChild("delFlag", 0);
        expression.addChild("exchangeCode", code);
        query.addCondition(expression);
        String sql = DaoUtils.getSql(PojoTables.DISCOUNT_EXCHANGE_CODE, query);
        DiscountExchangeCodeInfo discountExchangeCodeInfo = null;
        try {
            discountExchangeCodeInfo = (DiscountExchangeCodeInfo) UserDaoSql.getInstance().getObject(DiscountExchangeCodeInfo.class, sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return discountExchangeCodeInfo;
    }

    @Override
    public Object[] searchByPage(Long startTime, Long endTime, Integer isUse, Integer isExport, Integer page, Integer size) {
        Object[] result = new Object[2];
        result[0] = 0;
        result[1] = Collections.emptyList();
        StringBuilder sql = new StringBuilder();
        sql.append(" from ").append(PojoTables.DISCOUNT_EXCHANGE_CODE)
                .append(" where delFlag = 0 ");
        if (ValidateUtil.isAbsLong(startTime) && ValidateUtil.isAbsLong(endTime)) {
            sql.append(" and (startTime BETWEEN ").append(startTime).append(" and  ").append(endTime).append("  or  (endTime BETWEEN ").append(startTime).append(" and ").append(endTime).append(")) ");
        }
        if (isUse != null) {
            sql.append(" and isUse =").append(isUse);
        }
        List<DiscountExchangeCodeInfo> list = null;
        long count = 0L;
        String countSQL = " SELECT COUNT(id) as counts " + sql.toString();
        String selectSQL = " SELECT * " + sql.toString() + " order by id desc";
        if (isExport == 0) {
            selectSQL += " limit " + (page - 1) * size + "," + size;
        }
        try {
            if (isExport == 0) {
                count = UserDaoSql.getInstance().getCount(countSQL.toString());
                result[0] = count;
            }
            list = (List<DiscountExchangeCodeInfo>) UserDaoSql.getInstance().list(DiscountExchangeCodeInfo.class, selectSQL.toString());
            result[1] = list;
        } catch (Exception e) {
            e.printStackTrace();
            return result;
        }

        // 导出excel
        if (isExport == 1) {
            // 导出
            String path = discountExchangeCodeExcel(list);
            if (ValidateUtil.isNotNull(path)) {
                if (ValidateUtil.isNotNetUrl(path)) {
                    path = SYS_CONFIG_PATH.IMAGE_BASE_URL + path;
                }
                result[0] = path;
            }
        }
        return result;
    }

    // 导出账单的
    private String discountExchangeCodeExcel(List<DiscountExchangeCodeInfo> list) {
        String outputPath = "";
        try {
            outputPath = SYS_CONFIG_PATH.ORDER_IMAGE + "/" + DateUtils.getCurrentYearMonth() + "/" + DateUtils.getCurrTime() + ".xls";

            File outputFile = new File(SYS_CONFIG_PATH.IMAGE_BASE_FILE + outputPath);
            FileUtils.forceMkdirParent(outputFile);

            WritableWorkbook workbook = Workbook.createWorkbook(outputFile);
            WritableSheet sheet = workbook.createSheet("sheet1", 0);
            jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#0.00");   // 设置数字格式
            jxl.write.WritableCellFormat wcfN = new jxl.write.WritableCellFormat(nf); // 设置表单格式
            int col = 0;   // 列
            int row = 0;  // 行
            sheet.addCell(new Label(col++, row, "兑换码"));
            sheet.addCell(new Label(col++, row, "有效期"));
            sheet.addCell(new Label(col++, row, "状态"));
            sheet.addCell(new Label(col++, row, "创建时间"));
            row = 1;
            if (ValidateUtil.isAbsList(list)) {
                for (DiscountExchangeCodeInfo record : list) {
                    col = 0;
                    sheet.addCell(new Label(col++, row, ValidateUtil.isNull(record.getExchangeCode()) ? "" : record.getExchangeCode()));
                    sheet.addCell(new Label(col++, row, DateUtils.sdfDate.get().format(new Date(record.getStartTime())) + "至" + DateUtils.sdfDate.get().format(new Date(record.getEndTime()))));
                    sheet.addCell(new Label(col++, row, record.getIsUse() == 0 ? "未使用" : "已使用"));
                    sheet.addCell(new Label(col++, row, DateUtils.sdfDateTime.get().format(new Date(record.getCreateTime()))));
                    row++;     // 行
                }
            }
            workbook.write();
            workbook.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            outputPath = JYFileUtils.saveFile2Oss(outputPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return outputPath;
    }

    @Override
    public boolean useDiscountExchangeCode(String exchangeCode, String orderNo, Double discountMoney, Integer version, String username) {
        StringBuilder sql = new StringBuilder();
        sql.append(" update ").append(PojoTables.DISCOUNT_EXCHANGE_CODE)
                .append(" set isUse = 1 , orderNo ='").append(orderNo).append("', version = version +1 , useUsername = '").append(username).append("'")
                .append(" ,fcDiscountMoney =").append(discountMoney)
                .append(" , useTime = ").append(DateUtils.getCurrTime())
                .append(" where exchangeCode ='").append(exchangeCode).append("' and delFlag = 0 and version =").append(version);

        try {
            int updateCount = UserDaoSql.getInstance().executeUpdateBySql(sql.toString());
            return updateCount > 0;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            return false;
        }
    }

    /**
     * 订单取消回退订单
     *
     * @param exchangeCode
     * @param orderNo
     * @param opUser
     * @return
     */
    @Override
    public boolean orderCancelBackDisExchangeCode(String exchangeCode, String orderNo, String opUser) {
        if (ValidateUtil.isNull(orderNo)) {
            return false;
        }
        StringBuilder sql = new StringBuilder();
        sql.append(" update ").append(PojoTables.DISCOUNT_EXCHANGE_CODE).append(" set isUse = 0,useTime =null,fcDiscountMoney = 0.0, orderNo = null ,version = version +1, updateUser ='").append(opUser)
                .append("' where delFlag = 0  and isUse = 1 and orderNo ='").append(orderNo).append("' ");
        if (ValidateUtil.isNull(exchangeCode)) {
            sql.append(" and exchangeCode = '").append(exchangeCode).append("' ");
        }
        try {
            int updateCount = UserDaoSql.getInstance().executeUpdateBySql(sql.toString());
            return updateCount > 0;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            return false;
        }
    }


    /**
     * 批量生成
     *
     * @param info
     * @param codeList
     * @param conn
     * @throws SQLException
     */
    private void batchInsertExchangeCode(DiscountExchangeCodeInfo info, List<String> codeList, Connection conn) throws SQLException {
        StringBuffer infoSb = new StringBuffer(" INSERT INTO ").append(PojoTables.DISCOUNT_EXCHANGE_CODE)
                .append(" (exchangeCode,discountRate,isUse,startTime,endTime,")   // 5
                .append("delFlag,createUser,version,createTime)")  // 4
                .append("values(?,?,?,?,?,")
                .append("?,?,?,?)");
        PreparedStatement infoPre = null;
        infoPre = conn.prepareStatement(infoSb.toString());
        for (String code : codeList) {
            infoPre.setString(1, code);
            infoPre.setInt(2, info.getDiscountRate());
            infoPre.setInt(3, 0);
            infoPre.setLong(4, info.getStartTime());
            infoPre.setLong(5, info.getEndTime());
            infoPre.setInt(6, 0);
            infoPre.setString(7, info.getCreateUser());
            infoPre.setInt(8, 0);
            infoPre.setLong(9, info.getCreateTime());
            infoPre.addBatch();
        }
        // 添加
        infoPre.executeBatch();
    }


    /**
     * 批量生成兑换码
     *
     * @param pre
     * @param index
     * @param generateSize
     * @param containerList
     * @return
     */
    private Integer batchGenerateExchangeCode(String pre, int index, int generateSize, List<String> containerList) {
        return CommonUtils.generateExchangeCode(pre, index, generateSize, maxDigit, step, containerList);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
        // 最大位数
        String maxDigitStr = stringValueResolver.resolveStringValue("${exchange.code.maxDigit:9}");
        // 步长
        String stepStr = stringValueResolver.resolveStringValue("${exchange.code.step:1}");
        try {
            maxDigit = Integer.parseInt(maxDigitStr);
        } catch (Exception e) {
            maxDigit = 9;
        }

        try {
            step = Integer.parseInt(stepStr);
        } catch (Exception e) {
            step = 1;
        }
        System.out.println("兑换码参数控制maxDigit:" + maxDigit + " 步长->step :" + step);
    }

}
